import numpy as np

def mle(bn, data):
	
	nodes = list(bn.nodes())

	F = dict([(rv, {}) for rv in nodes])
	for i, n in enumerate(nodes):
		F[n]['values'] = list(np.unique(data[:,i]))
		bn.F[n]['values'] = list(np.unique(data[:,i]))

	obs_dict = dict([(rv,[]) for rv in nodes])
	for rv in nodes:
		p_idx = int(np.prod([bn.card(p) for p in bn.parents(rv)])*bn.card(rv))
		F[rv]['cpt'] = [0]*p_idx
		bn.F[rv]['cpt'] = [0]*p_idx
	
	for row in data:
		for rv in nodes:
			obs_dict[rv] = row[rv]

		for rv in nodes:
			rv_dict= { n: obs_dict[n] for n in obs_dict if n in bn.scope(rv) }
			offset = bn.cpt_indices(target = rv, val_dict = rv_dict)[0]
			F[rv]['cpt'][offset]+=1

	for rv in nodes:
		F[rv]['parents'] = [var for var in nodes if rv in bn.E[var]]
		for i in range(0,len(F[rv]['cpt']),bn.card(rv)):
			temp_sum = float(np.sum(F[rv]['cpt'][i:(i+bn.card(rv))]))
			for j in range(bn.card(rv)):
				F[rv]['cpt'][i+j] /= (temp_sum+1e-7)
				F[rv]['cpt'][i+j] = round(F[rv]['cpt'][i+j],5)
	bn.F = F